package com.scs.application.modules.finance.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.DateUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.finance.dto.PeriodCreateDTO;
import com.scs.application.modules.finance.entity.Period;
import com.scs.application.modules.finance.mapper.PeriodMapper;
import com.scs.application.modules.finance.service.PeriodService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Calendar;

/**
 * <p>
 * 服务实现类
 * </p>
 */
@Service
@Slf4j
public class PeriodServiceImpl extends BaseServiceImpl<PeriodMapper, Period> implements PeriodService {

    private int dayOfMonth = 20;

    @Override
    public boolean saveOrUpdate(Period entity) {
        Calendar calendarStart = Calendar.getInstance();
        calendarStart.setTime(entity.getStartDate());
        //00:00:00
        calendarStart.set(Calendar.HOUR_OF_DAY, 0);
        calendarStart.set(Calendar.MINUTE, 0);
        calendarStart.set(Calendar.SECOND, 0);
        calendarStart.set(Calendar.MILLISECOND, 0);
        entity.setStartDate(calendarStart.getTime());

        Calendar calendarEnd = Calendar.getInstance();
        calendarEnd.setTime(entity.getEndDate());
        //23:59:59
        calendarEnd.set(Calendar.HOUR_OF_DAY, 23);
        calendarEnd.set(Calendar.MINUTE, 59);
        calendarEnd.set(Calendar.SECOND, 59);
//        calendarEnd.set(Calendar.MILLISECOND, 999);
        entity.setEndDate(calendarEnd.getTime());

        if (StringUtils.isBlank(entity.getPeriod())) {
            String periodId = DateUtils.format(calendarStart.get(Calendar.DAY_OF_MONTH) > dayOfMonth ? entity.getStartDate() : entity.getEndDate(), "yyyyMM");
            int periodCount = baseMapper.selectCount(new QueryWrapper<Period>().like("period", periodId));
            if (periodCount > 0) {
                periodId = periodId + (periodCount < 10 ? "0" + periodCount : periodCount);
            }
            entity.setPeriod(periodId);
        }
        int startDuplicate = baseMapper.selectCount(new QueryWrapper<Period>().ne("id", entity.getId()).le("start_date", entity.getStartDate()).ge("end_date", entity.getStartDate()));
        int endDuplicate = baseMapper.selectCount(new QueryWrapper<Period>().ne("id", entity.getId()).le("start_date", entity.getEndDate()).ge("end_date", entity.getEndDate()));
        if(startDuplicate > 0 || endDuplicate > 0) {
            throw new BusinessException("你所设置的时间段与其他周期有重叠的部分，请确认后再修改！");
        }
        return super.saveOrUpdate(entity);
    }

    /**
     * 自动生成结算周期
     *
     * @param periodCreateDTO
     * @return
     */
    @Override
    public String autoCreatePeriod(PeriodCreateDTO periodCreateDTO) {
        if (periodCreateDTO.getStartDate() > 31 || periodCreateDTO.getStartDate() <= 0) {
            throw new BusinessException("生成周期范围不正确，必须是1到31之间的数字");
        }
        Calendar calendar = Calendar.getInstance(); //当前日期
        Calendar calendarStart; //开始日期
        Calendar calendarEnd; //结束日期
        //去掉时分秒
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        int buildNum = 0;
        for (int i = 0; i < periodCreateDTO.getMonths(); i++) {
            calendar.add(Calendar.MONTH, -1);
            calendarStart = (Calendar) calendar.clone();
            calendarStart.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DAY_OF_MONTH) > periodCreateDTO.getStartDate() ?
                    periodCreateDTO.getStartDate()
                    : calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
            Period period = new Period();
            calendarEnd = (Calendar) calendarStart.clone();
            calendarEnd.add(Calendar.MONTH, 1);
            calendarEnd.add(Calendar.SECOND, -1);
//            calendarEnd.add(Calendar.DATE, -1);

            //TODO 此处设计为每个月的结算时间大于20号，则视为计算的是下个月的
            String periodId = DateUtils.format(calendarStart.get(Calendar.DAY_OF_MONTH) > dayOfMonth ? calendarEnd.getTime() : calendarStart.getTime(), "yyyyMM");
            if (baseMapper.selectCount(new QueryWrapper<Period>().eq("period", periodId)) > 0) {
                log.error(String.format("%s的结算周期已经生成，无法继续生成！", periodId));
                continue;
            }
            period.setPeriod(periodId)
                    .setStartDate(calendarStart.getTime())
                    .setEndDate(calendarEnd.getTime())
                    .setStatus(0)
                    .setRemark("自动生成");
            super.save(period);
            buildNum++;
        }
        BusinessException.throwErrorIf(buildNum == 0,"所指定的条件已存在相关的结算周期，请勿重复生成");
        return StrUtil.format("生成结算周期数量: {}",buildNum);
    }
}
